![]() |
PATH![]() |
![]() ![]() |
The following Menu Manager methods for defining your own contextual menu plug-in are new with Appearance Manager 1.0:
Note
A contextual menu plug-in is implemented as a SOMObject object inside a shared library. (SOMObjects for the Mac OS platform is the Mac OS implementation of the System Object Model.) Typically your development environment can compile directly to a SOMObject object, so you do not need to create your own SOM interfaces.
A contextual menu plug-in is a subclass of AbstractCMPlugin : SOMObject . It consists of four methods described above. Each subclass of the AbstractCMPlugin must have an extended 'cfrg' resource, through which it identifies itself as a SOMObject object which derives from the AbstractCMPlugin class. See Mac OS Runtime Architectures for information about the extended 'cfrg' resource.
In addition you must register the plug-in class as a SOMObject object so that the Menu Manager can instantiate it by name. Typically you can do this in a fragment's initialization function.
Listing 1-1 shows a sample initialization function that registers the plug-in.
Listing 1-1 Registering a contextual menu plug-in
pascal OSErr MyPluginInitialize(CFragInitBlockPtr init)
{
/* If your compiler creates a default initialization function,*/
/* you should call it here */
/* Now register our class with SOM */
somNewClass(MyPlugIn);
return noErr;
}
The class declaration for a contextual menu definition plug-in is as follows:
class AbstractCMPlugin: SOMObject
{
OSStatus Initialize(FSSpec *inFileSpec);
OSStatus ExamineContext(AEDesc* inContextDescriptor,
SInt32 inTimeOutInTicks
AEDescList* ioCommandPairs,
Boolean* outNeedMoreTime);
OSStatus HandleSelection(AEDesc* inContextDescriptor, SInt32
inCommandID);
OSStatus PostMenuCleanup(void);
}
When writing your own contextual menu plug-in, you must follow this declaration and include the specified methods. The following sections describe these methods in detail.
Performs any required plug-in initialization. If you write a contextual menu plug-in, you may include an Initialize method with the following form:
OSStatus Initialize (FSSpec *inFileSpec);
The Initialize method is called when the Menu Manager builds its registry of available plug-ins (typically at system startup). You should use the Initialize method to check for available resources before the plug-in is actually required. To maintain a small memory footprint, the Initialize method should not allocate any memory, buffers, or so on. Instead, you should allocate memory as needed when examining the context or acting on the selection.
Available with Appearance Manager 1.0 and later.
Examines the context chosen by the user and determines possible menu commands appropriate to the context. If you write a contextual menu plug-in, it must contain an ExamineContext method with the following form:
OSStatus ExamineContext (AEDesc* inContextDescriptor,
SInt32 inTimeOutInTicks,
AEDescList* ioCommandPairs,
Boolean* outNeedMoreTime);
When the user activates a contextual menu, each module in the registry has its ExamineContext method called so it can inspect the context and add menu items as appropriate. After examining the context, the plug-in should then fill the AEDescList array with every command that it wants to add to the menu. This AEDescList will be created and disposed of for the plug-in; it will be empty when the plug-in receives it.
Each menu command that the plug-in can perform on the selection is described in an AERecord with two keyword-specified descriptor records. The structure of the AERecord is shown in Figure 1-1 .
Figure 1-1 A menu command list in the AEDescList array
The first descriptor ( keyAEName ) is of typeIntlText and contains the text of the menu item to be added to the menu. The second descriptor ( keyContextualMenuCommandID ) is of type typeLongInteger and must contain a value specific to the plug-in that uniquely identifies this menu item.
If a plug-in wants to display a submenu for a particular menu item, it must use a variation of the AERecord used to describe a normal menu item. Figure 1-2 shows this variation.
Figure 1-2 A menu record showing submenus
The first descriptor ( keyAEName ) is the same, but the second descriptor uses a different keyword ( keyContextualMenuSubmenu ) and is of type typeAEList . It must contain an AEDescList with an AERecord for every command to be added to the submenu. Submenu items can themselves have submenus by recursively using this technique. The depth of the submenus is limited only by the constraints of the Menu Manager.
Available with Appearance Manager 1.0 and later.
Executes the contextual menu item chosen by the user. If you write a contextual menu plug-in, it must contain a HandleSelection method with the following form:
OSStatus HandleSelection(AEDesc* inContextDescriptor,
SInt32 inCommandID);
If one of the plug-in's menu items is chosen, the Menu Manager calls the plug-in's HandleSelection method to execute the action. The plug-in should then perform the appropriate action.
Available with Appearance Manager 1.0 and later.
Performs any necessary cleanup when the contextual menu is dismissed. If you write a contextual menu plug-in, it must contain a PostMenuCleanup method with the following form:
OSStatus PostMenuCleanup(void);
When a contextual menu is dismissed (regardless of whether or not the user made a selection), the Menu Manager calls each plug-in's PostMenuCleanup method. The PostMenuCleanup method should do any necessary cleanup or memory deallocation. For example, a plug-in that allocated a buffer in the ExamineContext method should dispose of that buffer when PostMenuCleanup is called.